int enable);
int xc_readconsolering(int xc_handle,
- char *str,
- unsigned int max_chars,
+ char **pbuffer,
+ unsigned int *pnr_chars,
int clear);
typedef dom0_physinfo_t xc_physinfo_t;
return close(xc_handle);
}
-
-#define CONSOLE_RING_CLEAR 1
-
int xc_readconsolering(int xc_handle,
- char *str,
- unsigned int max_chars,
+ char **pbuffer,
+ unsigned int *pnr_chars,
int clear)
{
int ret;
dom0_op_t op;
+ char *buffer = *pbuffer;
+ unsigned int nr_chars = *pnr_chars;
op.cmd = DOM0_READCONSOLE;
- op.u.readconsole.str = (unsigned long)str;
- op.u.readconsole.count = max_chars;
- op.u.readconsole.cmd = clear ? CONSOLE_RING_CLEAR : 0;
+ op.u.readconsole.buffer = buffer;
+ op.u.readconsole.count = nr_chars;
+ op.u.readconsole.clear = clear;
- if ( (ret = mlock(str, max_chars)) != 0 )
+ if ( (ret = mlock(buffer, nr_chars)) != 0 )
return ret;
- if ( (ret = do_dom0_op(xc_handle, &op)) >= 0 )
- str[ret] = '\0';
+ if ( (ret = do_dom0_op(xc_handle, &op)) == 0 )
+ {
+ *pbuffer = op.u.readconsole.buffer;
+ *pnr_chars = op.u.readconsole.count;
+ }
- (void)munlock(str, max_chars);
+ (void)munlock(buffer, nr_chars);
return ret;
}
-
int xc_physinfo(int xc_handle,
xc_physinfo_t *put_info)
{
return 0;
}
-
int xc_sched_id(int xc_handle,
int *sched_id)
{
XcObject *xc = (XcObject *)self;
unsigned int clear = 0;
- char str[32768];
+ char _str[32768], *str = _str;
+ unsigned int count = 32768;
int ret;
static char *kwd_list[] = { "clear", NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
return NULL;
- ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
+ ret = xc_readconsolering(xc->xc_handle, &str, &count, clear);
if ( ret < 0 )
return PyErr_SetFromErrno(xc_error);
- return PyString_FromStringAndSize(str, ret);
+ return PyString_FromStringAndSize(str, count);
}
static PyObject *pyxc_physinfo(PyObject *self,
case DOM0_READCONSOLE:
{
- ret = read_console_ring(op->u.readconsole.str,
- op->u.readconsole.count,
- op->u.readconsole.cmd);
+ ret = read_console_ring(
+ &op->u.readconsole.buffer,
+ &op->u.readconsole.count,
+ op->u.readconsole.clear);
+ copy_to_user(u_dom0_op, op, sizeof(*op));
}
break;
void domain_crash(void)
{
- struct domain *d = current->domain;
-
- if ( d->domain_id == 0 )
- {
- show_registers(guest_cpu_user_regs());
- panic("Domain 0 crashed!\n");
- }
-
-#ifndef NDEBUG
+ printk("Domain %d (vcpu#%d) crashed on cpu#%d:\n",
+ current->domain->domain_id, current->vcpu_id, smp_processor_id());
show_registers(guest_cpu_user_regs());
-#endif
-
domain_shutdown(SHUTDOWN_crash);
}
#include <xen/spinlock.h>
#include <xen/console.h>
#include <xen/serial.h>
+#include <xen/softirq.h>
#include <xen/keyhandler.h>
#include <xen/mm.h>
#include <xen/delay.h>
static int xpos, ypos;
static unsigned char *video;
-#define CONSOLE_RING_SIZE 16392
-typedef struct console_ring_st
-{
- char buf[CONSOLE_RING_SIZE];
- unsigned int len;
-} console_ring_t;
-static console_ring_t console_ring;
+#define CONRING_SIZE 16384
+#define CONRING_IDX_MASK(i) ((i)&(CONRING_SIZE-1))
+static char conring[CONRING_SIZE];
+static unsigned int conringc, conringp;
static char printk_prefix[16] = "";
static void putchar_console_ring(int c)
{
- if ( console_ring.len < CONSOLE_RING_SIZE )
- console_ring.buf[console_ring.len++] = (char)c;
+ conring[CONRING_IDX_MASK(conringp++)] = c;
+ if ( (conringp - conringc) > CONRING_SIZE )
+ conringc = conringp - CONRING_SIZE;
}
-long read_console_ring(unsigned long str, unsigned int count, unsigned cmd)
+long read_console_ring(char **pstr, u32 *pcount, int clear)
{
- unsigned int len;
-
- len = (console_ring.len < count) ? console_ring.len : count;
-
- if ( copy_to_user((char *)str, console_ring.buf, len) )
- return -EFAULT;
+ char *str = *pstr;
+ u32 count = *pcount;
+ unsigned int p, q;
+ unsigned long flags;
- if ( cmd & CONSOLE_RING_CLEAR )
- console_ring.len = 0;
-
- return len;
+ /* Start of buffer may get overwritten during copy. So copy backwards. */
+ for ( p = conringp, q = count; (p > conringc) && (q > 0); p--, q-- )
+ if ( put_user(conring[CONRING_IDX_MASK(p-1)], (char *)str+q-1) )
+ return -EFAULT;
+
+ if ( clear )
+ {
+ spin_lock_irqsave(&console_lock, flags);
+ conringc = conringp;
+ spin_unlock_irqrestore(&console_lock, flags);
+ }
+
+ *pstr = str + q;
+ *pcount = count - q;
+ return 0;
}
__serial_rx(c, regs);
}
+long guest_console_write(char *buffer, int count)
+{
+ char kbuf[128];
+ int kcount;
+
+ while ( count > 0 )
+ {
+ while ( serial_tx_space(sercon_handle) < (SERIAL_TXBUFSZ / 2) )
+ {
+ if ( hypercall_preempt_check() )
+ break;
+ cpu_relax();
+ }
+
+ if ( hypercall_preempt_check() )
+ return hypercall3_create_continuation(
+ __HYPERVISOR_console_io, CONSOLEIO_write, count, buffer);
+
+ kcount = min_t(int, count, sizeof(kbuf)-1);
+ if ( copy_from_user(kbuf, buffer, kcount) )
+ return -EFAULT;
+ kbuf[kcount] = '\0';
+
+ serial_puts(sercon_handle, kbuf);
+
+ buffer += kcount;
+ count -= kcount;
+ }
+
+ return 0;
+}
+
long do_console_io(int cmd, int count, char *buffer)
{
- char *kbuf;
- long rc;
+ long rc;
#ifndef VERBOSE
- /* Only domain-0 may access the emergency console. */
+ /* Only domain 0 may access the emergency console. */
if ( current->domain->domain_id != 0 )
return -EPERM;
#endif
switch ( cmd )
{
case CONSOLEIO_write:
- if ( count > (PAGE_SIZE-1) )
- count = PAGE_SIZE-1;
- if ( (kbuf = (char *)alloc_xenheap_page()) == NULL )
- return -ENOMEM;
- kbuf[count] = '\0';
- rc = count;
- if ( copy_from_user(kbuf, buffer, count) )
- rc = -EFAULT;
- else
- serial_puts(sercon_handle, kbuf);
- free_xenheap_page((unsigned long)kbuf);
+ rc = guest_console_write(buffer, count);
break;
case CONSOLEIO_read:
rc = 0;
spin_unlock_irqrestore(&port->lock, flags);
}
+int serial_tx_space(int handle)
+{
+ struct serial_port *port = &com[handle & SERHND_IDX];
+ if ( handle == -1 )
+ return SERIAL_TXBUFSZ;
+ return SERIAL_TXBUFSZ - (port->txbufp - port->txbufc);
+}
+
void serial_init_preirq(void)
{
int i;
*/
#define DOM0_READCONSOLE 19
typedef struct {
- memory_t str;
- u32 count;
- u32 cmd;
+ /* IN variables. */
+ u32 clear; /* Non-zero -> clear after reading. */
+ /* IN/OUT variables. */
+ char *buffer; /* In: Buffer start; Out: Used buffer start */
+ u32 count; /* In: Buffer size; Out: Used buffer size */
} dom0_readconsole_t;
/*
void set_printk_prefix(const char *prefix);
-#define CONSOLE_RING_CLEAR 1
-long read_console_ring(unsigned long, unsigned int, unsigned int);
+long read_console_ring(char **, u32 *, int);
void init_console(void);
void console_endboot(int disable_vga);
void serial_start_sync(int handle);
void serial_end_sync(int handle);
+/* Return number of bytes headroom in transmit buffer. */
+int serial_tx_space(int handle);
+
/*
* Initialisation and helper functions for uart drivers.
*/